﻿//========================================
// All rights reserved (C) 2017-2100
// CLR 版本：	4.0.30319.42000
// 命名空间:	Common.XmlHandle
// 文 件 名：	XmlDownload
// 作    者：	WooG
// 联系方式：	wooglle@163.com
// 创建时间：	2018/6/23 10:59:59
//========================================
using System;
using System.IO;
using System.Threading;
using System.Xml;

namespace Common.XmlHandle
{
    public class XmlDownload
    {
        private XmlDocument xdoc;
        private XmlNode root;
        private string xmlPath;
        //public static ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();

        public string XmlPath { get => xmlPath; set => xmlPath = value; }

        public XmlDownload(string TempPath)
        {
            XmlPath = TempPath + "SFJD\\DownloadList.xml";
            string rootName = "DownloadList";
            try
            {
                xdoc = new XmlDocument();
                xdoc.Load(XmlPath);
                root = xdoc.SelectSingleNode(rootName);
                if (root == null)
                {
                    throw new Exception(XmlPath + " 路径下的XML文档结构错误。");
                }
            }
            catch (DirectoryNotFoundException)
            {
                Directory.CreateDirectory(XmlPath.Substring(0, XmlPath.LastIndexOf(@"\")));
                XmlDeclaration dec = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xdoc.AppendChild(dec);
                xdoc.AppendChild(xdoc.CreateElement(rootName));
                root = xdoc.SelectSingleNode(rootName);
                xdoc.Save(XmlPath);
            }
            catch (FileNotFoundException)
            {
                XmlDeclaration dec = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xdoc.AppendChild(dec);
                xdoc.AppendChild(xdoc.CreateElement(rootName));
                root = xdoc.SelectSingleNode(rootName);
                xdoc.Save(XmlPath);
            }
            catch (XmlException)
            {
                xdoc = new XmlDocument();
                XmlDeclaration dec = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xdoc.AppendChild(dec);
                xdoc.AppendChild(xdoc.CreateElement(rootName));
                root = xdoc.SelectSingleNode(rootName);
                xdoc.Save(XmlPath);
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定列表存入文件，如果存在相同的列表则返回已存在列表的GUID，否则返回null
        /// </summary>
        /// <param name="transFiles"></param>
        public Guid AddTransport(ClassTransportInfo transFiles)
        {
            //lockSlim.EnterWriteLock();
            xdoc.Load(XmlPath);
            foreach (XmlNode node in root.ChildNodes)//防止一个任务多次添加
            {
                ClassTransportInfo info = XmlNode2Transinfo(node);
                if (info == transFiles) return info.TransGuid;
            }
            try
            {
                XmlElement node = xdoc.CreateElement("List");
                node.SetAttribute("Guid", transFiles.TransGuid.ToString());
                node.SetAttribute("RootPath", transFiles.RootPath);
                root.AppendChild(node);
                foreach (ClassFileInfo file in transFiles.Files)
                {
                    addXmlNode(node, file);
                }
                xdoc.Save(XmlPath);
                //lockSlim.ExitWriteLock();
            }
            catch
            { }
            Thread.Sleep(100);
            return transFiles.TransGuid;
        }

        /// <summary>
        /// 指定guid的任务是否存在于xml文档
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public bool isThereGuid(Guid guid)
        {
            //lockSlim.EnterReadLock();
            xdoc.Load(XmlPath);
            XmlNodeList nodes = xdoc.LastChild.ChildNodes;
            foreach (XmlNode node in nodes)
            {
                XmlElement nod = node as XmlElement;
                if (new Guid(nod.GetAttribute("Guid")).Equals(guid))
                {
                    //lockSlim.ExitReadLock();
                    return true;
                }
            }
            //lockSlim.ExitReadLock();
            return false;
        }

        /// <summary>
        /// 根据制动GUID获取对应传输列表
        /// </summary>
        /// <param name="transGuid"></param>
        /// <returns></returns>
        public ClassTransportInfo GetTransInfo(Guid transGuid)
        {
            //Console.WriteLine("IsReadLockHeld: " + lockSlim.IsReadLockHeld + "   IsWriteLockHeld: " + lockSlim.IsWriteLockHeld +
            //    "\r\nCurrentReadCount: " + lockSlim.CurrentReadCount +
            //    "\r\nWaitingWriteCount: " + lockSlim.WaitingWriteCount +
            //    "\r\nWaitingReadCount: " + lockSlim.WaitingReadCount +
            //    "\r\nWaitingUpgradeCount: " +lockSlim.WaitingUpgradeCount);
            //Console.WriteLine("开始进入ReadLock");
            //lockSlim.EnterReadLock();
            //Console.WriteLine("进入ReadLock");
            xdoc.Load(XmlPath);
            XmlNodeList nodes = xdoc.LastChild.ChildNodes;
            ClassTransportInfo b = new ClassTransportInfo();
            foreach (XmlNode node in nodes)
            {
                XmlElement nod = node as XmlElement;
                Guid guid = new Guid(nod.GetAttribute("Guid"));
                if (guid.Equals(transGuid))
                {
                    b.TransGuid = guid;
                    b.RootPath = nod.GetAttribute("RootPath");
                    XmlNodeList nos = nod.ChildNodes;
                    foreach (XmlNode no in nos)
                    {
                        XmlElement ele = no as XmlElement;
                        ClassFileInfo file = new ClassFileInfo();
                        file.RelativePath = ele.GetAttribute("Path");
                        file.FileSize = long.Parse(ele.GetAttribute("Size"));
                        b.Files.Add(file);
                    }
                    break;
                }
            }
            //lockSlim.ExitReadLock();
            return b;
        }

        /// <summary>
        /// 删除指定GUID传输列表
        /// </summary>
        /// <param name="guid"></param>
        public void RemoveByGuid(Guid guid)
        {
            //lockSlim.EnterWriteLock();
            XmlNodeList nodes = root.ChildNodes;
            foreach (XmlNode node in nodes)
            {
                XmlElement nod = node as XmlElement;
                if (guid.Equals(new Guid(nod.GetAttribute("Guid"))))
                {
                    node.ParentNode.RemoveChild(node);
                }
            }
            xdoc.Save(XmlPath);
            //lockSlim.ExitWriteLock();
        }

        public void RemovePathByIndex(Guid guid, int index)
        {
            //lockSlim.EnterWriteLock();
            XmlNodeList nodes = root.ChildNodes;
            foreach (XmlNode node in nodes)
            {
                XmlElement nod = node as XmlElement;
                if (nod.GetAttribute("Guid").Equals(guid.ToString()))
                {
                    XmlNodeList nos = nod.ChildNodes;
                    nos[index].RemoveAll();
                }
            }
            xdoc.Save(XmlPath);
            //lockSlim.ExitWriteLock();
        }

        ////////////////////////////////////xml基础操作//////////////////////////////////
        private void addXmlNode(XmlNode node, ClassFileInfo file)
        {
            XmlElement ele = xdoc.CreateElement("File");
            ele.SetAttribute("Path", file.RelativePath);
            ele.SetAttribute("Size", file.FileSize.ToString());
            node.AppendChild(ele);
        }

        private ClassTransportInfo XmlNode2Transinfo(XmlNode xmlNode)
        {
            ClassTransportInfo b = new ClassTransportInfo();
            XmlElement nod = xmlNode as XmlElement;

            b.TransGuid = new Guid(nod.GetAttribute("Guid"));
            b.RootPath = nod.GetAttribute("RootPath");
            XmlNodeList nos = nod.ChildNodes;
            foreach (XmlNode no in nos)
            {
                XmlElement ele = no as XmlElement;
                ClassFileInfo file = new ClassFileInfo();
                file.RelativePath = ele.GetAttribute("Path");
                file.FileSize = long.Parse(ele.GetAttribute("Size"));
                b.Files.Add(file);
            }
            return b;
        }
    }
}
